package com.linkai.JUC._16_cas;

import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @Description: 乐观锁和悲观锁：CAS机制实现乐观锁
 *              参考：https://www.cnblogs.com/kismetv/p/10787228.html
 *              乐观锁和悲观锁是2种思想，用于解决办法并发场景下的数据竞争问题。
 *              乐观锁：操作数据时十分乐观，认为别人不会修改数据，因此不会上锁；只在更新的时候判断一下在此期间别人
 *                      是否修改了数据，如果别人修改了数据则放弃操作，否则执行操作
*               悲观锁：操作数据时比较悲观，认为别人会修改数据，因此操作数据时会把数据锁住，直到操作完成之后才会释放锁，
 *                      上锁期间其他人不能修改数据
 *              乐观锁的实现机制主要有2种：CAS机制和版本号机制
 *              悲观锁的实现方式是加锁
 *
 *              AtomicInteger原子类：
 *              通过 volatile 保证“可见性”和“有序性”；
 *              CAS操作保证原子性（但是CAS操作只能保证单个共享变量的原子性）
 *
 *              原子类底层的的 getAndIncrement() 方法是调用 unsafe 类的 getAndIncrement() 方法实现的。
 *              原子类内部维护了一个用 volatile 修饰的 value 变量，getAndIncrement() 就是对该 value 对象进行操作。
 *
 * @Author: 林凯
 * @Date: 2021/11/4 16:24
 */
public class OptimisticPessimisticLock {

    // value1：线程不安全
    private static int value1 = 0;
    // value2：使用乐观锁
    private static AtomicInteger value2 = new AtomicInteger(0);
    // value3：使用悲观锁
    private static int value3 = 0;
    private static synchronized void increaseValue3() {
        value3++;
    }


    public static void main(String[] args) throws InterruptedException {
        // 开启1000个线程，并执行自增操作
        for (int i = 0; i < 10000; i++) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        // 模拟延时，增加出问题的可能性
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    value1++;
                    value2.getAndIncrement();
                    increaseValue3();
                }
            }).start();
        }


        while (Thread.activeCount() > 2) {
            System.out.println(Thread.activeCount());
            // main线程和gc线程是常驻的
            // 上面的线程还没执行完，main线程就一直在这里while循环
        }
        System.out.println("线程不安全，value1=" + value1);
        System.out.println("乐观锁（AtomicInteger）value2=" + value2);
        System.out.println("悲观锁（Synchronize）value3=" + value3);
    }


}
